package ar.uba.fi.taller2.jh.WebService;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Random;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import ar.uba.fi.taller2.jh.B23tree.B23tree;
import ar.uba.fi.taller2.jh.BEtree.BETree;
import ar.uba.fi.taller2.jh.BPtree.BPTree;
import ar.uba.fi.taller2.jh.BStree.BSTree;
import ar.uba.fi.taller2.jh.Btree.BTree;
import ar.uba.fi.taller2.jh.Tree.Tree;

public class Parser {
	private Document dom;
	private Arboles arboles;
	
	public Parser() {
		super();
		this.dom = null;
		this.arboles = new Arboles();
	}

	
	

	public void parseXmlFile(String fileName){
		//get the factory
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try {

			//Using factory get an instance of document builder
			DocumentBuilder db = dbf.newDocumentBuilder();

			//parse using builder to get DOM representation of the XML file
			dom = db.parse(fileName);


		}catch(ParserConfigurationException pce) {
			pce.printStackTrace();
		}catch(SAXException se) {
			se.printStackTrace();
		}catch(IOException ioe) {
			ioe.printStackTrace();
		}
	}
	private String execute(){
		//NodeList ArbolNode=dom.getElementsByTagName("Arbol");
		//Node method=webServiceNode.getElementByTagName("Metodo");
		String id=null;
		String tipo=null;
		String result="";
		if (dom.getElementsByTagName("IdArbol").item(0)!=null)
		   id=dom.getElementsByTagName("IdArbol").item(0).getTextContent().toString();
		if (dom.getElementsByTagName("Tipo").item(0)!=null)
			tipo=dom.getElementsByTagName("Tipo").item(0).getTextContent().toString();
		if (tipo==null){
			tipo=arboles.getTipo(id);
		}
		String method=dom.getElementsByTagName("Metodo").item(0).getTextContent().toString();
		result+=executeMethod(id, tipo,method, dom);
		return 		result;
	}
	private String executeMethod(String id, String tipo, String method, Document dom2) {
		//TODO: hace falta agregar los metodos
		//Agregar
		String result="";
		Integer order=4;
		
		//Agregar
		if (method.equals("Agregar")) {
			Tree tree=arboles.getArbol(id);
			NodeList registrosNode=dom.getElementsByTagName("Registro");
			if(registrosNode != null && registrosNode.getLength() > 0) {
				for(int i = 0 ; i < registrosNode.getLength();i++) {

					//get the employee element
					Element el = (Element)registrosNode.item(i);
					tree.addKey(new Integer(getTextValue(el,"Clave"))  );
					result+=getTextValue(el,"Clave")+":agregado ";
				}
			}
		}
		
		//Borrar
		if (method.equals("Borrar")) {
			Tree tree=arboles.getArbol(id);
			NodeList registrosNode=dom.getElementsByTagName("Registro");
			if(registrosNode != null && registrosNode.getLength() > 0) {
				for(int i = 0 ; i < registrosNode.getLength();i++) {
					Element el = (Element)registrosNode.item(i);
					result+=getTextValue(el,"Clave")+":borrado ";
				}
			}
		}
		
		//Crear
		if (method.equals("Crear")) {
			Tree tree=arboles.getArbol(id);
			if (tree==null)  {
				tree=createTree(tipo,order,4);
				id=arboles.agregarArbol(tree,tipo );
				tipo=arboles.getTipo(id);
				result+="Arbol "+id+" creado ";
			}else 
			result+="Error creando arbol  "+id;
		}
		
		//imprimir
		if (method.equals("Imprimir")) {
			Tree tree=arboles.getArbol(id);
			if (tree!=null)  {
				result=tree.imprimir().toString();
			}else 
			result+="Error imprimiendo arbol  "+id;
		}
		
		//Destruir
		if (method.equals("Destruir")) {
			Tree tree=arboles.getArbol(id);
			if (tree==null)  {
				result+="el Arbol no existe"+id;
			}else {
				
			}
			result+="Error creando arbol  "+id;
		}
		
        return "<?xml version=\"1.0\" encoding=\"UTF-8\"?><WebService xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"respuesta.xsd\">" +
		"<Arbol>" +
		  "<Metodo>"+method+"</Metodo>" +
		  "<Tipo>"+tipo+"</Tipo>" +
		  "<IdArbol>"+id+"</IdArbol>" +
		  "</Arbol>" +
		"<Respuesta>" +
		" 	<Codigo>0</Codigo>" +
		"	<Descripcion>"+result+"</Descripcion>" +
		"</Respuesta></WebService>";
	}




	private Tree createTree(String type,Integer order, Integer leafSize){
		Comparador comp= new Comparador();
		if (type.equals("BP")) return new BPTree(comp,order);
		if (type.equals("BS")) return new BSTree(comp,order);
		if (type.equals("B23")) return new B23tree(comp,order);
		if (type.equals("B34")) return new BPTree(comp,order);
		if (type.equals("BE")) return new BETree(comp,order);
		if (type.equals("B")) return new BTree(comp,order);
		
		

		return null;
	}
	private String executeMethod(Tree tree,String method,Element el ){
		//TODO: hace falta agregar los metodos
		if (method.equals("Agregar")) {
			tree.addKey(new Integer(getTextValue(el,"Clave"))  );
			return getTextValue(el,"Clave")+":agregado ";
		}
		if (method.equals("Borrar")) {
			tree.remove(new Integer(getTextValue(el,"Clave") ) );
			return getTextValue(el,"Clave")+":removido ";
		}
		if (method.equals("Crear")) {
			/*tree.remove(getTextValue(el,"Clave")  );
			return getTextValue(el,"Clave")+":removido ";*/
		}
		if (method.equals("Imprimir")) {
			/*tree.remove(getTextValue(el,"Clave")  );
			return getTextValue(el,"Clave")+":removido ";*/
		}
		if (method.equals("Destruir")) {
			/*tree.remove(getTextValue(el,"Clave")  );
			return getTextValue(el,"Clave")+":removido ";*/
		}
		return "OK";
		
	}
	
/*	private void getEntry(Element el) {
		String valor = getTextValue(el,"Valor");
		Integer clave = getIntValue(el,"Clave");
	
	}*/
	private String getTextValue(Element ele, String tagName) {
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}
	private int getIntValue(Element ele, String tagName) {
		//in production application you would catch the exception
		return Integer.parseInt(getTextValue(ele,tagName));
	}
	
	public String agregar (String id,String clave){
		Tree tree=arboles.getArbol(id);
		Random generator = new Random();
		Integer next = new Integer(generator.nextInt(200));
		if (clave==null ) clave=next.toString();
				
		tree.addKey(new Integer(clave) );
		return "Clave"+clave+":agregado ";
	}
	public String crear (String tipo,Integer order){
		Integer leafSize=order;
			Tree tree=createTree(tipo,order,leafSize);
			String result = null;
			if (tree!=null)  {
				if (arboles==null) this.arboles = new Arboles();
			String id=arboles.agregarArbol(tree,tipo );
			
			tipo=arboles.getTipo(id);
			result= id;
			}else 
				result="-1";
		    return result;
			
		
		
	}
	public String quitar (String id,String clave){
		Tree tree=arboles.getArbol(id);
		String result = null;
		if (tree!=null)  {
			Object resp=tree.remove(new Integer(clave)  );
			if (resp!=null)
				return  "Clave"+clave+":eliminada ";
			return "El registro "+clave+" no existe";
		}else 
			result+="Error eliminando registro"+clave+" arbol  "+id;
	    return result;
			
	}
	public String imprimir(String id){
		Tree tree=arboles.getArbol(id);
		String filename = "";
		String result = "";
		Integer i=0;
		if (tree!=null)  {
			FileWriter file;
			try {
				ArrayList<String> pseudos=tree.getPseudos();
				for (String print: tree.imprimir()){
					
					filename="arbol"+System.currentTimeMillis()+i.toString()+".svg";
					file = new FileWriter("./webapps/ROOT/arbol/svg/"+filename);
					file.write(print);
					file.close();
					result+=filename+","+pseudos.get(i)+";";
					i++;
				}
				tree.reset();
	 		    return result;
				
				

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}else 
		result+="Error imprimiendo arbol  "+id;
		return result;
	}
	
	
	
	
	
	
	
	public String destruir (String id){
		String result="";
		Tree tree=arboles.getArbol(id);

		if (tree==null)  {
			result+="el Arbol no existe"+id;
		}else {
			arboles.removeArbol(id);
			result="el arbol "+id+"fue borrado";
		}
		return result;
	}
	
	class Comparador implements Comparator{

		public int compare(Object emp1, Object emp2){

		//

		Integer emp1Name = ( (Integer) emp1 );

		Integer emp2Name = ( (Integer) emp2 );

		//

		return emp1Name.compareTo(emp2Name);

		}

		}

}
